# stories/forms.py
# 功能：定义所有表单，用于用户注册、登录、故事发布、评论、评分等

from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser, Story, Comment, Rating, SensitiveWord


class CustomUserCreationForm(UserCreationForm):
    """
    功能：
        - 允许用户注册账号
        - 支持邮箱、手机号（可选）
        - 取消密码强度限制
        - 校验用户名、邮箱唯一性
    """

    # 添加邮箱和手机号字段（可选）
    email = forms.EmailField(required=False, help_text="可选，用于登录")
    phone = forms.CharField(max_length=20, required=False, help_text="可选")

    class Meta:
        model = CustomUser
        # 指定表单包含的字段（注意：password1和password2是UserCreationForm自带的）
        fields = ('username', 'email', 'phone', 'password1', 'password2')

    def __init__(self, *args, **kwargs):
        """初始化方法：给每个输入框添加 Bootstrap 样式"""
        super().__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'  # 统一添加样式类

        # 自定义密码帮助文本，让用户知道无强度限制
        self.fields['password1'].help_text = '请输入密码，无强度限制'
        self.fields['password2'].help_text = '再次输入相同密码进行确认'

    def clean_email(self):
        """ 邮箱唯一性校验（数据库层面）"""
        email = self.cleaned_data.get('email')
        if email and CustomUser.objects.filter(email=email).exists():
            raise forms.ValidationError('该邮箱已被注册')
        return email

    def clean_username(self):
        """ 用户名唯一性校验（忽略大小写，防止 'Alice' 和 'alice' 冲突）"""
        username = self.cleaned_data.get('username')
        if CustomUser.objects.filter(username__iexact=username).exists():
            raise forms.ValidationError('该用户名已被注册，请选择其他用户名')
        return username

    def clean_password1(self):
        """ 取消密码强度验证，直接返回原始密码"""
        password1 = self.cleaned_data.get('password1')
        return password1

    def clean_password2(self):
        """ 验证两次密码是否一致"""
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError('两次输入的密码不一致')
        return password2

    def _post_clean(self):
        """
        【修复后】
        目标：跳过密码强度验证，但保留密码哈希和唯一性校验
        方法：
            1. 先调用父类 UserCreationForm 的 _post_clean → 它会设置密码哈希 + 做唯一性校验
            2. 然后清空 self._errors 中由密码验证器产生的错误（即“密码太简单”等）
        """
        super()._post_clean()  # 关键：确保 set_password 被调用！

        # 清除密码验证器产生的错误（保留其他错误，如唯一性冲突）
        if 'password2' in self._errors:
            password_errors = self._errors['password2']
            # 过滤掉所有密码强度相关的错误（通常包含 "This password is too"）
            filtered_errors = [
                error for error in password_errors
                if not str(error).startswith("This password is too")
            ]
            if filtered_errors:
                self._errors['password2'] = filtered_errors
            else:
                del self._errors['password2']  # 如果只剩密码强度错误，就全部删除


class CustomUserChangeForm(UserChangeForm):
    """
     自定义用户信息修改表单
    功能：
        - 修改用户名、邮箱、手机号、头像、简介
        - 不显示密码字段（安全考虑）
    """
    password = None  # 隐藏密码字段

    class Meta:
        model = CustomUser
        fields = ('username', 'email', 'phone', 'avatar', 'bio')
        widgets = {
            'bio': forms.Textarea(attrs={'rows': 4, 'placeholder': '请输入个人简介...'}),
        }

    def __init__(self, *args, **kwargs):
        """初始化：添加样式类"""
        super().__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            if field_name != 'avatar':
                field.widget.attrs['class'] = 'form-control'
        self.fields['avatar'].widget.attrs['class'] = 'form-control-file'  # 文件上传特殊样式


class StoryForm(forms.ModelForm):
    """
     故事发布/编辑表单
    功能：
        - 输入标题、内容、封面、分类、状态
    """

    class Meta:
        model = Story
        fields = ['title', 'detailed_description', 'content', 'cover_image', 'category']
        widgets = {
            'title': forms.TextInput(attrs={'placeholder': '请输入故事标题...'}),
            'detailed_description': forms.Textarea(attrs={'rows': 3, 'placeholder': '请输入详细描述，帮助AI更精确地生成内容...'}),
            'content': forms.Textarea(attrs={'rows': 15, 'placeholder': '请输入故事内容...'}),
            'status': forms.RadioSelect(),  # 单选按钮：草稿/发布
        }
        labels = {
            'title': '故事标题',
            'detailed_description': '详细描述',
            'content': '故事内容',
            'cover_image': '封面图片',
            'category': '故事分类',
        }

    def __init__(self, *args, **kwargs):
        """初始化：添加样式类"""
        super().__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            if field_name not in ['cover_image']:
                field.widget.attrs['class'] = 'form-control'
            elif field_name == 'cover_image':
                field.widget.attrs['class'] = 'form-control-file'


class CommentForm(forms.ModelForm):
    """
     评论表单
    """

    class Meta:
        model = Comment
        fields = ['content']
        widgets = {
            'content': forms.Textarea(attrs={
                'rows': 3,
                'placeholder': '请输入您的评论...',
                'class': 'form-control'
            }),
        }
        labels = {
            'content': '评论内容',
        }


class RatingForm(forms.ModelForm):
    """
     评分表单（1-5星）
    """

    class Meta:
        model = Rating
        fields = ['score']
        # 生成 1-5 星的单选按钮
        widgets = {
            'score': forms.RadioSelect(choices=[(i, f'{i}星') for i in range(1, 6)]),
        }
        labels = {
            'score': '评分',
        }

    def __init__(self, *args, **kwargs):
        """初始化：为评分单选按钮添加特殊样式类（可用于CSS控制）"""
        super().__init__(*args, **kwargs)
        self.fields['score'].widget.attrs['class'] = 'star-rating-input'


class StoryReviewForm(forms.ModelForm):
    """
    故事审核表单
    """
    class Meta:
        model = Story
        fields = ['status', 'rejection_reason']
        widgets = {
            'status': forms.RadioSelect(),
            'rejection_reason': forms.Textarea(attrs={'rows': 4, 'placeholder': '请输入驳回原因（仅在驳回时填写）'}),
        }
        labels = {
            'status': '审核结果',
            'rejection_reason': '驳回原因',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 只显示审核相关的状态选项
        self.fields['status'].choices = [
            ('published', '通过'),
            ('rejected', '驳回'),
        ]
        self.fields['rejection_reason'].widget.attrs['class'] = 'form-control'
        
    def clean(self):
        cleaned_data = super().clean()
        status = cleaned_data.get('status')
        rejection_reason = cleaned_data.get('rejection_reason')
        
        if status == 'rejected' and not rejection_reason:
            raise forms.ValidationError('驳回时必须填写驳回原因')
            
        return cleaned_data


class SensitiveWordForm(forms.ModelForm):
    """
    敏感词管理表单
    """
    class Meta:
        model = SensitiveWord
        fields = ['word', 'is_active']
        widgets = {
            'word': forms.TextInput(attrs={'placeholder': '请输入敏感词'}),
        }
        labels = {
            'word': '敏感词',
            'is_active': '是否启用',
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.widget.attrs['class'] = 'form-control'